package org.six11.olive3.server;

import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import javax.sql.DataSource;

import org.six11.olive3.net.Message;
import org.six11.olive3.net.MessageHandler;
import org.six11.olive3.net.MessageNames;
import org.six11.olive3.net.OliveStreamHandler;
import org.six11.util2.Debug;
import org.six11.olive3.server.OliveRuntimeData.Route;

/**
 * 
 * 
 * @author Gabe Johnson <johnsogg@cmu.edu>
 */
public class InkBroker extends HttpServlet {

  public static final String DATASOURCE_NAME = "jdbc/sketching_games";

  protected OliveStreamHandler handler;
  protected OliveRuntimeData data;
  protected RecordMessageHandler recordMessageHandler;
  protected MessageHandler debugMessageHandler;
  protected DatabaseThing dbThing;

  // protected Map<String, List<Message>> privateMessages;

  /**
   * Make an InkBroker with a default OliveStreamHandler.
   */
  public InkBroker() throws NamingException{
    super();
    data = new OliveRuntimeData();
    handler = new OliveStreamHandler();
    
    Context env = (Context) new InitialContext().lookup("java:comp/env");
    dbThing = new DatabaseThing((DataSource) env.lookup(DATASOURCE_NAME));

    // each user can have a private message queue. If applications (subclasses of InkBroker) need to
    // give a message to one user in particular it may be more convenient to use these private
    // queues instead. This is useful for cases when the client and server communicate to negotiate
    // some transient info that is irrelevent beyond the here and now.
    // privateMessages = new HashMap<String, List<Message>>();

    // register the 'record' message handler. This is responsible for adding messages to the global
    // queue. The routing strategies determine who gets which messages. Any message type that is
    // added to the recordMessageHandler will be added to the global queue, but those messages will
    // only be routed to the clients that should get it.
    recordMessageHandler = new RecordMessageHandler(data);

    // make a debugging message handler, probably useful to subclasses.
    debugMessageHandler = new MessageHandler() {
      public void handleLater(Message m) {
        bug("Got message type: " + m.name);
      }
    };
  }

  public void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException,
      IOException {
    PrintWriter out = res.getWriter();
    out.println("I don't support GET requests! Begone, ye!");
    out.close();
  }

  protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException,
      IOException {
    HttpSession session = req.getSession();
    PrintWriter out = resp.getWriter();
    try {
      handler.handle(req.getInputStream(), out);
      out.close();
    } catch (Exception ex) {
      out.println("Unknown error: " + ex);
      Debug.out("InkBroker", "Got unknown exception.");
      ex.printStackTrace();
    }
  }

  private static void bug(String what) {
    Debug.out("InkBroker", what);
  }
}
